<template>
  <div class="basic-form">
    <el-form :model="formModal" ref="vForm" v-on="$listeners" v-bind="$attrs" :rules="formRules">
      <el-row :gutter="16">
        <el-col v-for="item in v_formColumns" :key="item.prop" :span="item.colSpan || colSpan">
          <el-form-item :prop="item.prop" :label="item.label">
            <!-- 单行输入框表单组件 -->
            <template v-if="item.type === 'input'">
              <el-input
                v-model="formModal[item.prop]"
                v-bind="item.componentProp"
                v-on="item.componentEvent"
                style="width: 100%"
              ></el-input>
            </template>
            <!-- 数字输入框表单组件 -->
            <template v-if="item.type === 'input-number'">
              <el-input-number
                v-model="formModal[item.prop]"
                v-bind="item.componentProp"
                v-on="item.componentEvent"
                :controls="false"
                style="width: 100%"
              ></el-input-number>
            </template>
            <!-- 地址选择表单组件 -->
            <template v-if="item.type === 'address'">
              <district-select
                v-model="formModal[item.prop]"
                v-bind="item.componentProp"
                v-on="item.componentEvent"
                style="width: 100%"
              />
            </template>
            <!-- 级联选择表单组件 -->
            <template v-if="item.type === 'cascader'">
              <el-cascader
                v-model="formModal[item.prop]"
                v-bind="item.componentProp"
                v-on="item.componentEvent"
                style="width: 100%"
              />
            </template>
            <!-- 单选/多选表单组件 -->
            <template v-if="item.type === 'select'">
              <el-select
                v-model="formModal[item.prop]"
                v-bind="item.componentProp"
                v-on="item.componentEvent"
                style="width: 100%"
              >
                <el-option
                  v-for="itemOption in item.options"
                  :key="itemOption.value"
                  :label="itemOption.label"
                  :value="itemOption.value"
                ></el-option>
              </el-select>
            </template>
            <!-- 日期选择表单组件 -->
            <template v-if="item.type === 'date-picker'">
              <el-date-picker
                v-model="formModal[item.prop]"
                v-bind="item.componentProp"
                v-on="item.componentEvent"
                :value-format="item.format"
                type="datetimerange"
                range-separator="-"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                :default-time="['00:00:00', '23:59:59']"
                style="width: 100%"
              ></el-date-picker>
            </template>
            <!-- 时间选择表单组件 -->
            <template v-if="item.type === 'time-picker'">
              <el-time-select
                v-model="formModal[item.prop]"
                v-bind="item.componentProp"
                v-on="item.componentEvent"
                style="width: 100%"
              >
              </el-time-select>
            </template>
            <!-- 文件上传表单组件 -->
            <template v-if="item.type === 'upload-file'">
              <div style="position: relative; display: inline-block; width: 100%">
                <file-upload
                  v-model="formModal[item.prop]"
                  v-bind="item.componentProp"
                  v-on="item.componentEvent"
                  style="width: 100%"
                />
              </div>
            </template>
            <!-- 图片上传表单组件 -->
            <template v-if="item.type === 'upload-image'">
              <div style="position: relative; display: inline-block; width: 100%">
                <image-upload
                  v-model="formModal[item.prop]"
                  v-bind="item.componentProp"
                  v-on="item.componentEvent"
                  style="width: 100%"
                />
              </div>
            </template>
            <!-- 视频上传表单组件 -->
            <template v-if="item.type === 'upload-video'">
              <div style="position: relative; display: inline-block; width: 100%">
                <video-upload
                  v-model="formModal[item.prop]"
                  v-bind="item.componentProp"
                  v-on="item.componentEvent"
                  style="width: 100%"
                />
              </div>
            </template>
            <!-- 富文本表单组件 -->
            <template v-if="item.type === 'rich-text'">
              <div style="position: relative; display: inline-block; width: 100%">
                <editor
                  v-model="formModal[item.prop]"
                  :min-height="192"
                  v-bind="item.componentProp"
                  v-on="item.componentEvent"
                />
              </div>
            </template>
            <!-- 自定义表单组件 -->
            <template v-if="item.type === 'custom'">
              <slot :name="item.prop" :formdata="formModal"></slot>
            </template>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>
<script lang="js">
export default {
  inheritAttrs: false,
  props: {
    colSpan: {
      type: Number,
      default: 24,
    },
    data: {
      type: Object,
      default: () => ({}),
    },
    columns: {
      type: Array,
      default: () => [],
    },
  },
  model: {
    prop: 'data',
    event: 'change',
  },
  watch: {
    data: {
      deep: true,
      immediate: true,
      handler() {
        this.initData();
      },
    },
    formModal: {
      deep: true,
      handler() {
        this.$emit('change', this.formModal);
      },
    },
    columns: {
      deep: true,
      immediate: true,
      handler() {
        this.initColumns();
      },
    },
    // 这个监听主要用来控制表单字段隐藏显示，不做其他逻辑，
    // 其他逻辑在initColumns方法中去实现
    formColumns: {
      deep: true,
      handler() {
        this.v_formColumns = this.formColumns.filter((item) => !item.hide);
      },
    },
  },
  created() {},
  data() {
    return {
      v_formColumns: [],
      formColumns: [],
      formRules: {},
      formModal: {},
    };
  },
  methods: {
    initColumns() {
      this.formColumns = this.columns;
      console.log(this.formColumns, '......')
      this.columns.map((item) => {
        this.formRules[item.prop] = item.rules;
        this.$set(this.formModal, item.prop, this.data[item.prop]);
      });
    },
    initData() {
      this.columns.map((item) => {
        this.$set(this.formModal, item.prop, this.data[item.prop]);
      });
    },
    /**
     * 获取表单实例
     * @returns HTMLElement 返回表单实例
     */
    getForm() {
      return this.$refs.vForm;
    },
    /**
     * 设置表单字段配置(多个)
     * @param columnsProp 要设置的字段keys
     * @param value 要设置的字段key的配置值列表
     *
     * ```js
     *  this.$refs.['自定义的ref名称'].getForm().setColumns('prop1,prop2', [
     *    {
     *     prop: 'prop1',
     *     type: 'input',
     *     label: '',
     *     componentProp: {
     *       clearable: true,
     *       placeholder: '',
     *     },
     *     componentEvent: {},
     *     rules: [{ required: true, trigger: 'blur', message: '不能为空' }],
     *     },
     *    {
     *    prop: 'prop2',
     *     type: 'input',
     *     label: '',
     *     componentProp: {
     *       clearable: true,
     *       placeholder: '',
     *     },
     *     componentEvent: {},
     *     rules: [{ required: true, trigger: 'blur', message: '不能为空' }],
     *     },
     *    }
     *  ])
     * ```
     */
    setColumns(columnsProp, value) {
      let props = columnsProp.split(',');
      console.log(columnsProp, value, '.........')
      props.map((prop, propIndex) => {
        let flag = false;
        this.formColumns = this.formColumns.map((item) => {
          if (item.prop === prop) {
            if (value[propIndex].rules) {
              this.formRules[item.prop] = value[propIndex].rules;
            }
            flag = true;
            return {
              ...item,
              ...value[propIndex],
            };
          }
          return item;
        });
        if (!flag) {
          this.formColumns.push(value[propIndex]);
        }
      });
    },
    /**
     * 获取当前字段配置
     * @param columnsProp
     */
    getColumn(columnsProp) {
      return this.formColumns.find((item) => item.prop === columnsProp);
    },
    /**
     * 隐藏多个表单字段显示
     * @param columnsProp
     */
    hideColumns(columnsProp) {
      let props = columnsProp.split(',');
      props.map((prop) => {
        this.setColumns(prop, [
          {
            hide: true,
          },
        ]);
      });
    },
    /**
     * 显示多个表单字段
     * @param columnsProp
     */
    visibleColumns(columnsProp) {
      let props = columnsProp.split(',');
      props.map((prop) => {
        this.setColumns(prop, [
          {
            hide: false,
          },
        ]);
      });
    },
    /**
     * 删除一个表单字段
     * @param columnsProp 要删除的字段key
     */
    deleteColumn(columnsProp) {
      this.formColumns = this.formColumns.filter((item) => item.prop !== columnsProp);
      delete this.formRules[columnsProp];
      delete this.formModal[columnsProp];
    },
    /**
     * 设置表单字段值(多个)
     * @param `columnsProp` 要设置的字段keys
     * @param `value` 要设置的字段key的值列表
     * ```js
     *  setDatas('prop1,prop2', [value1, value2])
     * ```
     */
    setDatas(columnsProp, value) {
      let props = columnsProp.split(',');
      props.map((prop, propIndex) => {
        Object.keys(this.formModal).map((key) => {
          if (key === prop) {
            this.$set(this.formModal, key, value[propIndex]);
          }
        });
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.basic-form {
  ::v-deep .el-form--label-top {
    .el-form-item {
      display: inline-block;
    }
  }
  ::v-deep .el-form-item {
    width: 100%;
    display: flex;
    label {
      display: block;
      flex-shrink: 0;
    }
    .el-form-item__content {
      width: 100%;
      margin: 0 !important;
    }
  }
}
</style>
